 /*
 * Created on 29/11/2004
 *
 */
//TODO validation before ok action
package br.unb.graphics;

import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

import java.util.ResourceBundle;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import br.unb.core.traffic.Traffic;
import br.unb.core.manager.Manager;
import br.unb.plugins.geral.model.GeneratorModel;
import br.unb.plugins.geral.view.XmlFrame;
import br.unb.plugins.geral.view.XmlComboBox;
import br.unb.plugins.geral.view.XmlFactory;
import br.unb.statistic.InterPacketTimeGenerator;
import br.unb.statistic.RandomGenerator;
import br.unb.statistic.distribution.SelfSimilarFGNGenerator;
import br.unb.utils.Console;
import br.unb.utils.Path;
import br.unb.utils.Resource;
import br.unb.utils.LogFile;
import br.unb.utils.LogPrinter;

// Panel called to add new traffics:
public class NewTrafficPanel extends JPanel {

    //internal data
    private ResourceBundle resource = Resource.NewTrafficPanel;
    private GridBagConstraints c = new GridBagConstraints();
    //Name
    private JLabel nameLabel;
    private JTextField nameField;
    //Source ip
    private JLabel srcLabel;
    private JTextField srcIpField;
    private JTextField srcPortField;
    //Destination ip
    private JLabel dstLabel;
    private JTextField dstIpField;
    private JTextField dstPortField;
    //Packet source selection
    private JLabel packetDataLabel;
    private JComboBox packetDataCombo;
    //Packet source 1: random interval
    private JPanel fromIntervalPanel;
    //->Start time
    private JLabel startLabel;
    private JTextField startField;
    //->Duration
    private JLabel durationLabel;
    private JTextField durationField;
    //Packet source 2: File
    //->File
    private JPanel fromFilePanel;
    private JTextField fromFileField;
    private JButton fromFileButton;
    private JFileChooser fromFileChooser;
    //Pause model
    private JLabel pauseLabel;
    private JComboBox pauseTypeCombo;
    private GeneratorModel pauseModel;
    private JLabel pauseLabelCurrent;
    //Lenght model
    private JLabel lengthLabel;
    private JComboBox lengthTypeCombo;
    private GeneratorModel lengthModel;
    private JLabel lengthLabelCurrent;
    //Type of service
    private JLabel tosLabel;
    private JComboBox tosField;
    private String[] tosStrings = new String[]{"BE", "AF1", "AF2", "AF3", "EF"};
    //Buttons
    private JButton add, simulateFileButton;
    private JButton save, load;
    /*******************************/
    /****  actions and files  ******/
    /*******************************/
    private LogFile trafficFile;
    AddTrafficAction addAction = new AddTrafficAction();
    LoadTrafficAction loadAction = new LoadTrafficAction();
    SaveTrafficAction saveAction = new SaveTrafficAction();
    SimulateAction simulateAction = new SimulateAction();
    private Action[] actions = {
        addAction,
        loadAction,
        saveAction,
        saveAction,};
    /*******************************/
    public static NewTrafficPanel INSTANCE = new NewTrafficPanel();

    public static NewTrafficPanel getInstance() {
        return INSTANCE;
    }

    private NewTrafficPanel() {
        super(new GridBagLayout());

        nameLabel = new JLabel(resource.getString("TRAFFIC_NAME"));
        nameField = new JTextField(9);

        srcLabel = new JLabel(resource.getString("SOURCE(IP/PORT)"));
        srcIpField = new JTextField(9);
        srcPortField = new JTextField(6);

        dstLabel = new JLabel(resource.getString("DESTINATION(IP/PORT)"));
        dstPortField = new JTextField(6);
        dstIpField = new JTextField(9);

        packetDataLabel = new JLabel(resource.getString("PACKET_DATA"));
        packetDataCombo = new JComboBox(
                new String[]{resource.getString("RANDOM"),
                    resource.getString("FILE")});
        packetDataCombo.addItemListener(new ItemListener() {

            public void itemStateChanged(ItemEvent e) {
                if (packetDataCombo.getSelectedIndex() == 1) {
                    fromFilePanel.setVisible(true);
                    fromIntervalPanel.setVisible(false);
                } else {
                    fromFilePanel.setVisible(false);
                    fromIntervalPanel.setVisible(true);
                }
            }
        });

        fromIntervalPanel = new JPanel(new FlowLayout());
        {
            startLabel = new JLabel(resource.getString("START"));
            startField = new JTextField(4);
            durationLabel = new JLabel(resource.getString("DURATION"));
            durationField = new JTextField(4);

            c.insets = new Insets(1, 1, 1, 1);
            c.anchor = GridBagConstraints.EAST;
            c.gridx = 1;
            {
                c.gridy = 1;
                fromIntervalPanel.add(startLabel, c);
                c.gridy = 2;
                fromIntervalPanel.add(startField, c);
            }
            c.gridx = 2;
            {
                c.gridy = 1;
                fromIntervalPanel.add(durationLabel);
                c.gridy = 2;
                fromIntervalPanel.add(durationField);
            }
        }
        fromFilePanel = new JPanel(new FlowLayout());
        {
            fromFileField = new JTextField(15);
            fromFileChooser = new JFileChooser();
            fromFileButton = new JButton(
                    resource.getString("OPEN"),
                    new ImageIcon(Path.getResourceUrlByAddress("16x16/open.png")));
            fromFileButton.addActionListener(
                    new ActionListener() {

                        public void actionPerformed(ActionEvent e) {
                            int o = fromFileChooser.showOpenDialog(null);
                            switch (o) {
                                case JFileChooser.APPROVE_OPTION: {
                                    File file = fromFileChooser.getSelectedFile();
                                    fromFileField.setText(file.getAbsolutePath());
                                }
                                break;
                                case JFileChooser.CANCEL_OPTION: {
                                }
                                break;
                            }
                        }
                    });

            fromFilePanel.add(fromFileField);
            fromFilePanel.add(fromFileButton);
        }

        tosLabel = new JLabel(resource.getString("TOS"));
        tosField = new JComboBox(tosStrings);

        pauseLabel = new JLabel(resource.getString("TRAFFIC_TYPE"));
        pauseTypeCombo = new XmlComboBox("TrafficTypes.xml");
        pauseTypeCombo.addActionListener(
                new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        pauseModel = ((XmlComboBox) pauseTypeCombo).getFrame().getGenModel();
                        if (pauseModel != null) {
                            pauseLabelCurrent.setText((String) pauseTypeCombo.getSelectedItem());
                        }

                    }
                });
        pauseLabelCurrent = new JLabel("");

        lengthLabel = new JLabel(resource.getString("SIZE"));
        lengthTypeCombo = new XmlComboBox("PacketLengthTypes.xml");
        lengthTypeCombo.addActionListener(
                new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        lengthModel = ((XmlComboBox) lengthTypeCombo).getFrame().getGenModel();
                        if (lengthModel != null) {
                            lengthLabelCurrent.setText((String) lengthTypeCombo.getSelectedItem());
                        }
                    }
                });

        lengthLabelCurrent = new JLabel("");

        add = new JButton(resource.getString("ADD"));
        add.addActionListener(addAction);

        simulateFileButton = new JButton(resource.getString("SIMULATION"));
        simulateFileButton.addActionListener(simulateAction);

        save = new JButton(
                "SAVE",// resource.getString("SAVE"),
                new ImageIcon(Path.getResourceUrlByAddress("16x16/save.png")));

        save.addActionListener(saveAction);

        load = new JButton(
                "LOAD",//resource.getString("LOAD"),
                new ImageIcon(Path.getResourceUrlByAddress("16x16/open.png")));
        load.addActionListener(loadAction);


        /* Grid Construction*/
        c.insets = new Insets(1, 1, 1, 1);
        c.anchor = GridBagConstraints.CENTER;
        c.gridx = 0;
        c.gridy = 0;
        //.add(new Label("Generate new traffic"), c);
        c.anchor = GridBagConstraints.EAST;
        c.gridx = 0;
        {
            c.gridy = 1;
            this.add(nameLabel, c);
            c.gridy = 2;
            this.add(srcLabel, c);
            c.gridy = 3;
            this.add(dstLabel, c);
            c.gridy = 4;
            this.add(pauseLabel, c);
            c.gridy = 5;
            this.add(lengthLabel, c);
            c.gridy = 6;
            this.add(tosLabel, c);
            c.gridy = 7;
            this.add(packetDataLabel, c);
            c.gridy = 8;
            c.gridy = 9;
            c.gridy = 10;
        }
        c.anchor = GridBagConstraints.WEST;
        c.gridx = 1;
        {
            c.gridy = 1;
            JPanel namePanel = new JPanel(new FlowLayout());
            namePanel.add(nameField);
            this.add(namePanel, c);

            c.gridy = 2;
            JPanel srcIpPortPanel = new JPanel(new FlowLayout());
            srcIpPortPanel.add(srcIpField);
            srcIpPortPanel.add(srcPortField);
            this.add(srcIpPortPanel, c);

            c.gridy = 3;
            JPanel dstIpPortPanel = new JPanel(new FlowLayout());
            dstIpPortPanel.add(dstIpField);
            dstIpPortPanel.add(dstPortField);
            this.add(dstIpPortPanel, c);

            c.gridy = 4;
            JPanel pausePanel = new JPanel(new FlowLayout());
            //pauseTypeCombo.setSize(200, 30);
            pausePanel.add(pauseTypeCombo);
            this.add(pauseTypeCombo, c);

            c.gridy = 5;
            JPanel lengthPanel = new JPanel(new FlowLayout());
            //lengthTypeCombo.setSize(200, 30);
            lengthPanel.add(lengthTypeCombo);
            this.add(lengthTypeCombo, c);

            c.gridy = 6;
            JPanel tosPanel = new JPanel(new FlowLayout());
            tosPanel.add(tosField);
            this.add(tosPanel, c);

            c.gridy = 7;
            JPanel comboPanel = new JPanel(new FlowLayout());
            comboPanel.add(packetDataCombo);
            this.add(comboPanel, c);

            c.gridy = 8;
            this.add(fromFilePanel, c);
            fromFilePanel.setVisible(false);
            this.add(fromIntervalPanel, c);

            c.gridy = 9;
            JPanel addPanel = new JPanel(new FlowLayout());
            addPanel.add(add);
            addPanel.add(simulateFileButton);
            this.add(addPanel, c);

            //c.gridy = 9;
            //JPanel savePanel = new JPanel(new FlowLayout());
            addPanel.add(save);
            addPanel.add(load);
            //this.add(savePanel, c);
        }
        c.gridx = 2;
        {
            c.gridy = 1;

            c.gridy = 2;

            c.gridy = 3;

            c.gridy = 4;
            this.add(pauseLabelCurrent, c);

            c.gridy = 5;
            this.add(lengthLabelCurrent, c);

            c.gridy = 6;

            c.gridy = 7;

            c.gridy = 8;

            c.gridy = 9;
        }
    }

    public Traffic validateTraffic() {
        //TODO validation here!! before creating Traffic class
        if (nameField.getText().isEmpty() || nameField.getText().equals("")) {
            return null;
        }
        try {
            Traffic t = new Traffic(
                    nameField.getText(),
                    srcIpField.getText(),
                    srcPortField.getText(),
                    dstIpField.getText(),
                    dstPortField.getText(),
                    startField.getText(),
                    durationField.getText(),
                    tosField.getSelectedItem().toString(),
                    (String) pauseTypeCombo.getSelectedItem(),
                    pauseModel,
                    (String) lengthTypeCombo.getSelectedItem(),
                    lengthModel,
                    (this.packetDataCombo.getSelectedIndex() == 0
                    ? null
                    : (String) this.packetDataCombo.getSelectedItem()));
            return t;
        } catch (IllegalArgumentException e) {
            Console.printError("FAIL_TO_BUILD_TRAFFIC");
            return null;
        }
    }

    private void populateFields(Traffic t) {
        //TODO validate traffic before inserting text into fields
        nameField.setText(t.getName());
        srcIpField.setText(t.getSrcIP().getHostAddress());
        srcPortField.setText(Integer.toString(t.getSrcPort()));
        dstIpField.setText(t.getDstIP().getHostAddress());
        dstPortField.setText(Integer.toString(t.getDstPort()));
        startField.setText(Integer.toString(t.getStart()));
        durationField.setText(Integer.toString(t.getDuration()));
        tosField.setSelectedItem(t.getTos());
        pauseTypeCombo.setSelectedIndex(0);
        pauseModel = t.getPauseModel();
        pauseLabelCurrent.setText(t.getPauseType());//pauseTypeCombo.setSelectedItem(t.getPauseType());
        lengthTypeCombo.setSelectedIndex(0);
        lengthLabelCurrent.setText(t.getLengthType());//lengthTypeCombo.setSelectedItem(t.getLengthType());
        lengthModel = t.getLengthModel();
        fromFileField.setText(t.getPath());
        if (fromFileField.getText().equals("none")) {
            packetDataCombo.setSelectedIndex(0);
        } else {
            packetDataCombo.setSelectedIndex(1);
        }

    }

    /*********************************************************************/
    /*********************         ACTIONS           *********************/
    /*********************************************************************/
    class AddTrafficAction extends AbstractAction {

        public AddTrafficAction() {
            super("AddTrafficAction");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (validateTraffic() == null) {
                Console.showMessageDialog("Inform a Valid Traffic First");
                return;
            }
            Manager.getInstance().newTraffic(validateTraffic());
            GraphicInterface.trafficTable.updateData();
            GraphicInterface.getInstance().showTrafficTable();

        }
    }

    class SaveTrafficAction extends AbstractAction {

        public SaveTrafficAction() {
            super("SaveTrafficAction");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            JFileChooser fc = new JFileChooser(Path.getLogDir());
            fc.setFileFilter(LogFile.Type.TRAFFIC.getFileFilter());
            fc.setDialogTitle("Save Traffic File");
            int o = fc.showSaveDialog(GraphicInterface.getInstance().getParent());
            switch (o) {
                case JFileChooser.APPROVE_OPTION:
                    File temp = fc.getSelectedFile();
                    trafficFile = new LogFile(LogFile.Type.TRAFFIC, temp.getName());
                    if (trafficFile == null) {
                        Console.printError(Resource.getString("SELECT_VALID_FILE"));
                        return;
                    }
                    break;

                case JFileChooser.CANCEL_OPTION:
                    Console.printError(Resource.getString("NO_FILE_CHOOSEN"));
                    trafficFile = null;
                    return;
            }
            if (trafficFile == null) {
                Console.println(Resource.getString("FILE_NOT_FOUND"));
                return;

            } else {
                if (trafficFile.exists()) {
                    Console.printError(Resource.getString("WARNING_FILE_EXISTS"));
                }
                try {
                    Traffic t = validateTraffic();
                    String xml = XmlFactory.getXmlFromTraffic(t);
                    //trafficFile.write(s);
                    FileWriter fw = new FileWriter(trafficFile);
                    fw.write(xml);
                    fw.flush();
                    fw.close();
                    Console.showMessageDialog(Resource.getString("TRAFFIC_WRITTEN_TO_FILE") + trafficFile.getName());
                } catch (Exception ex) {
                    Console.showMessageDialog(
                            trafficFile.toString() + "\n" + "DOES_NOT_CONTAIN_VALID_XML_TRAFFIC");
                }
            }
        }
    }

    class LoadTrafficAction extends AbstractAction {

        public LoadTrafficAction() {
            super("LoadTrafficAction");
        }

        public void actionPerformed(ActionEvent e) {
            JFileChooser fc = new JFileChooser(Path.getLogDir());
            fc.setFileFilter(LogFile.Type.TRAFFIC.getFileFilter());
            fc.setDialogTitle("Open Traffic File");
            int o = fc.showOpenDialog(GraphicInterface.getInstance().getParent());
            switch (o) {
                case JFileChooser.APPROVE_OPTION:
                    File temp = fc.getSelectedFile();
                    String ext = LogFile.stripExtension(temp);
                    String defExt = LogFile.Type.TRAFFIC.getExtension();
                    if (ext.equals(defExt)) {
                        trafficFile = new LogFile(LogFile.Type.TRAFFIC, LogFile.stripExtension(temp, false));
                        if (trafficFile != null) {
                        } else {
                            Console.printError(Resource.getString("SELECT_VALID_FILE"));
                        }
                    } else {
                        Console.printError(Resource.getString("SELECT_VALID_EXTENSION"));
                        trafficFile = null;
                    }
                    break;

                case JFileChooser.CANCEL_OPTION:
                    Console.printError(Resource.getString("NO_FILE_CHOOSEN"));
                    trafficFile = null;
                    return;
            }

            if (trafficFile == null) {
                Console.println(Resource.getString("FILE_NOT_FOUND"));
                return;
            } else if (!trafficFile.exists()) {
                Console.println(Resource.getString("FILE_NOT_FOUND") + trafficFile.getPath());
                return;
            } else if ((trafficFile.length()) <= 0) {
                Console.println(Resource.getString("FILE_SEEMS_EMPTY") + trafficFile.getPath());
            } else {
                try {
                    FileReader fr = new FileReader(trafficFile);
                    char[] buffer = new char[10240];
                    fr.read(buffer);
                    String xml = new String(buffer);
                    Traffic t = XmlFactory.getTrafficFromXml(xml);
                    populateFields(t);
                    fr.close();
                } catch (Exception ex) {
                    Console.showMessageDialog(
                            trafficFile.toString() + "\n" + "DOES_NOT_CONTAIN_VALID_XML_TRAFFIC");
                }
            }
        }
    }

    class SimulateAction extends AbstractAction {
        //simulates the sending of the packets on the sender machine
        //The files resembles the .sender file

        public SimulateAction() {
            super("SimulateAction");
        }

        public void actionPerformed(ActionEvent e) {
            if (validateTraffic() == null) {
                Console.showMessageDialog("Inform a Valid Traffic First");
                return;
            }
            //Generator 1: time
            double stopTime = Double.parseDouble(durationField.getText());
            double startTime = Double.parseDouble(startField.getText());
            double duration = stopTime - startTime;
            pauseModel.setParameter("duration", "" + duration);
            pauseModel.setParameter("name", nameField.getText());
            InterPacketTimeGenerator pauseGenerator = (InterPacketTimeGenerator) pauseModel.getGenerator();
            if (pauseGenerator != null) {
            }

            //Generator 2: length
            RandomGenerator lengthGenerator = (RandomGenerator) lengthModel.getGenerator();
            int length = (int) lengthGenerator.rand();

            //Logging SimulateFile
            double time = startTime;
            int nrPacket = 1;
            try {
                LogFile l = new LogFile(
                        LogFile.Type.SIMULATE,
                        nameField.getText());
                LogPrinter simulatePrinter = new LogPrinter(l);

                while (time < stopTime) {
                    simulatePrinter.logEntry(
                            nrPacket, length, time, 0);
                    time += pauseGenerator.nextInterPacketTime(); //Generator 1: time
                    length = (int) lengthGenerator.rand();        //Generator 2: length
                    nrPacket++;
                }
                Console.showMessageDialog(Resource.getString("SIMULATION_SUCESSFULLY_GENERATED" + l.getName()));
            } catch (NullPointerException npe) {
                Console.showMessageDialog("FILE_NOT_FOUND");
                return;
            } finally {
                if (pauseGenerator instanceof SelfSimilarFGNGenerator) {
                    ((SelfSimilarFGNGenerator) pauseGenerator).finalize();
                }
            }
        }
    }
}
